package com.iwop.moto.service.impl;

import com.iwop.moto.cache.RedisUtil;
import com.iwop.moto.cache.SerializeUtil;
import com.iwop.moto.comm.ConponConstant;
import com.iwop.moto.dao.FUserLotteryDao;
import com.iwop.moto.model.*;
import com.iwop.moto.service.*;
import com.iwop.moto.utils.stringUtil.JsonUtils;
import com.iwop.moto.utils.stringUtil.ObjectId;
import com.opslab.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Service("fUserLotteryService")
public class FUserLotteryServiceImpl implements FUserLotteryService {

    org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(FUserLotteryServiceImpl.class);

    @Autowired
    private FUserLotteryDao fUserLotteryDao;

    @Autowired
    private UserService userService;

    @Autowired
    private FCouponService fCouponService;
    @Autowired
    private StoreService storeService;

    @Autowired
    private MCouponConfigService configService;
    @Autowired
    MCouponSchemeService mCouponSchemeService;

//    @Autowired
//    MCouponScheme mCouponScheme;


    @Override
    public int add(FUserLottery fUserLottery) {
        return fUserLotteryDao.add(fUserLottery);
    }

    @Override
    public int update(FUserLottery fUserLottery) {
        return fUserLotteryDao.update(fUserLottery);
    }

    @Override
    public int del(String sid) {
        return fUserLotteryDao.del(sid);
    }

    @Override
    public Integer findOneByUserIdAndOrderId(String lotteryUserId, String orderId) {
        return fUserLotteryDao.findOneByUserIdAndOrderId(lotteryUserId, orderId);
    }


    public List<String> getCouponListByClientTypeAndMoney(String clientType, Double money) {

        //获取对应客户端类型开启的配置表
        MCouponConfig mCouponConfig = null;
        try {
            mCouponConfig = getmCouponConfig(clientType);
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug(clientType + "配置表错误");
            return returnDefulCoupon();
        }
        if (mCouponConfig == null) {
            List<String> list = new ArrayList<>();
            list.add("0800102458199883fc2382d7ccf5a000");
            return list;
        }
        Jedis jedis = null;
        try {
            jedis = RedisUtil.getJedis();
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug("jedis clients  is full");
            return null;
        }
        byte[] key = SerializeUtil.serialize(money.toString() + clientType.toString() + mCouponConfig.getSchemeTable());
        List<MCouponScheme> allByMoney = new ArrayList<>();
        if (jedis.exists(key)) {
            logger.info("缓存命中" + SerializeUtil.serialize(money.toString() + clientType.toString() + mCouponConfig.getSchemeTable()));
            byte[] bytes = jedis.get(key);
            allByMoney = (List<MCouponScheme>) SerializeUtil.unserialize(bytes);
        } else {
            allByMoney = getSchemeAndAddCache(clientType, money, mCouponConfig, jedis);
            if (allByMoney.isEmpty()) {
                logger.debug("区间错误");
                FErrorLog errorLog = new FErrorLog();
                errorLog.setErrContent(money + "元区间未找到");
                errorLog.setErrData("getCouponListByClientTypeAndMoney.getSchemeAndAddCache");
                errorLog.setErrTime(new Date());
                if (jedis != null) {
                    jedis.close();
                }
                return returnDefulCoupon();
            }
        }
        if (jedis != null) {
            jedis.close();
        }
        List<String> list = new ArrayList<>();
        int rundom = getRundom(99, 0);
        for (int i = 0; i < allByMoney.size(); i++) {
            MCouponScheme mCouponScheme = allByMoney.get(i);
            String percent = mCouponScheme.getPercent().trim();
            String[] split = percent.split("-");
            if (split.length != 2) {
                list.add("0800102458199883fc2382d7ccf5a003");
                continue;
            }
            if (Integer.parseInt(split[0]) <= rundom && rundom < Integer.parseInt(split[1])) {
                list.add(mCouponScheme.getCouponId());
            }
        }
        return list;
    }

    public List<String> returnDefulCoupon() {
        List<String> list = new ArrayList<>();
        list.add("0800102458199883fc2382d7ccf5a003");
        return list;
    }

    /**
     * 查询数据并添加redis 缓存
     *
     * @param clientType
     * @param money
     * @param mCouponConfig
     * @param jedis
     * @return
     */
    public List<MCouponScheme> getSchemeAndAddCache(String clientType, Double money, MCouponConfig mCouponConfig, Jedis jedis) {
        List<MCouponScheme> allByMoney;//获取方案区间的优惠券信息
        logger.info("--------------缓存未命中------查询数据库.....");
        allByMoney = getmCouponSchemes(money, mCouponConfig);
        if (allByMoney.isEmpty()) {
            return allByMoney;
        }
        byte[] key = SerializeUtil.serialize(money.toString() + clientType.toString() + mCouponConfig.getSchemeTable());
        jedis.set(key, SerializeUtil.serialize(allByMoney));
        logger.info("--------------插入缓存-----------");
        jedis.expire(key, 600);
        logger.info("缓存过期时间" + 600 + "秒");
        return allByMoney;
    }

    /**
     * 根据金额和配置表 查询优惠券区间方案
     *
     * @param money
     * @param mCouponConfig
     * @return
     */
    public List<MCouponScheme> getmCouponSchemes(Double money, MCouponConfig mCouponConfig) {
        Map map = new HashMap();
        map.put("tableName", mCouponConfig.getSchemeTable());
        map.put("money", money);
        List<MCouponScheme> scheme = mCouponSchemeService.getScheme(map);
        return scheme;
    }

    /**
     * 获取可用的优惠券配置
     *
     * @param clientType
     * @return
     */
    public MCouponConfig getmCouponConfig(String clientType) throws Exception {
        Jedis jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            String key = clientType + "open";
            if (jedis.exists(key)) {
                String value = jedis.get(key);
                MCouponConfig mCouponConfig = JsonUtils.jsonToBean(value, MCouponConfig.class);
                return mCouponConfig;
            }
            MCouponConfig pre = new MCouponConfig();
            pre.setClientType(clientType);
            pre.setIsEnabled("1");
            MCouponConfig configByClientType = configService.getConfigByClientType(pre);
            jedis.set(clientType + "open", JsonUtils.toJsonString(configByClientType));
            jedis.expire(key, 180);
            return configByClientType;
        } catch (Exception e) {
            throw new Exception(e.toString());
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
//        String key = clientType + "open";
//        if (jedis.exists(key)) {
//            String value = jedis.get(key);
//            MCouponConfig mCouponConfig = JsonUtils.jsonToBean(value, MCouponConfig.class);
//            if (jedis != null) {
//                jedis.close();
//            }
//            return mCouponConfig;
//        }
//        MCouponConfig pre = new MCouponConfig();
//        pre.setClientType(clientType);
//        pre.setIsEnabled("1");
//        MCouponConfig configByClientType = configService.getConfigByClientType(pre);
//        jedis.set(clientType + "open", JsonUtils.toJsonString(configByClientType));
//        jedis.expire(key, 180);
//        if (jedis != null) {
//            jedis.close();
//        }
// return configByClientType;
    }

    /**
     * 核心抽奖
     *
     * @param superRecordModel
     * @return
     */
    @Override
    public BigDecimal doDraw(Double money) {
        Integer moneys = Integer.valueOf((int) Math.floor(money));
        BigDecimal userBouns = null;
        if ((10 <= moneys) && (moneys < 15)) {
            userBouns = section_10_15();

        } else if ((15 <= moneys) && (moneys < 23)) {
            userBouns = section_15_23();

        } else if (23 <= moneys && moneys < 33) {
            userBouns = section_23_33();

        } else if (33 <= moneys && moneys < 39) {
            userBouns = section_33_39();

        } else if (39 <= moneys && moneys < 53) {
            userBouns = section_39_53();
        } else if (53 <= moneys && moneys < 77) {
            userBouns = section_53_77();
        } else if (77 <= moneys && moneys < 106) {
            userBouns = section_77_106();
        } else if (106 <= moneys && moneys < 149) {
            userBouns = section_106_149();
        } else if (149 <= moneys && moneys < 218) {
            userBouns = section_149_218();
        } else if (218 <= moneys && moneys < 264) {
            userBouns = section_218_264();
        } else if (264 <= moneys && moneys < 326) {
            userBouns = section_264_326();
        }
        return userBouns;
    }

    private BigDecimal section_264_326() {
        int s = getRundom(100, 1);
        if (s <= 5) {
            return BigDecimal.valueOf(7);
        } else if (5 < s && s <= 25) {
            return BigDecimal.valueOf(8);
        } else if (25 < s && s <= 65) {
            return BigDecimal.valueOf(9);
        } else {
            return BigDecimal.valueOf(10);
        }
    }

    private BigDecimal section_218_264() {
        int s = getRundom(100, 1);
        if (s <= 5) {
            return BigDecimal.valueOf(5);
        } else if (5 < s && s <= 10) {
            return BigDecimal.valueOf(6);
        } else if (10 < s && s <= 70) {
            return BigDecimal.valueOf(7);
        } else {
            return BigDecimal.valueOf(8);
        }
    }


    private BigDecimal section_149_218() {
        int s = getRundom(100, 1);
        if (s <= 5) {
            return BigDecimal.valueOf(5);
        } else if (5 < s && s <= 25) {
            return BigDecimal.valueOf(6);
        } else if (25 < s && s <= 85) {
            return BigDecimal.valueOf(7);
        } else {
            return BigDecimal.valueOf(8);
        }

    }

    private BigDecimal section_106_149() {
        int s = getRundom(100, 1);
        if (s <= 10) {
            return BigDecimal.valueOf(4);
        } else if (10 < s && s <= 30) {
            return BigDecimal.valueOf(5);
        } else if (30 < s && s <= 90) {
            return BigDecimal.valueOf(6);
        } else {
            return BigDecimal.valueOf(7);
        }

    }

    private BigDecimal section_77_106() {
        int s = getRundom(100, 1);
        if (s <= 5) {
            return BigDecimal.valueOf(2);
        } else if (5 < s && s <= 10) {
            return BigDecimal.valueOf(3);
        } else if (10 < s && s <= 80) {
            return BigDecimal.valueOf(4);
        } else if (80 < s && s <= 90) {
            return BigDecimal.valueOf(5);
        } else {
            return BigDecimal.valueOf(6);
        }
    }

    private BigDecimal section_53_77() {
        int s = getRundom(100, 1);
        if (s <= 5) {
            return BigDecimal.valueOf(2);
        } else if (5 < s && s <= 10) {
            return BigDecimal.valueOf(3);
        } else if (10 < s && s <= 80) {
            return BigDecimal.valueOf(4);
        } else if (80 < s && s <= 90) {
            return BigDecimal.valueOf(5);
        } else {
            return BigDecimal.valueOf(6);
        }
    }

    private BigDecimal section_39_53() {
        int s = getRundom(100, 1);
        if (s <= 5) {
            return BigDecimal.valueOf(2);
        } else if (5 < s && s <= 40) {
            return BigDecimal.valueOf(3);
        } else if (40 < s && s <= 75) {
            return BigDecimal.valueOf(4);
        } else {
            return BigDecimal.valueOf(5);
        }
    }

    private BigDecimal section_33_39() {
        int s = getRundom(100, 1);
        if (s <= 20) {
            return BigDecimal.valueOf(2);
        } else if (20 < s && s <= 80) {
            return BigDecimal.valueOf(3);
        } else {
            return BigDecimal.valueOf(4);
        }

    }


    private void section_big() {
        final int maximumbonus = 1;

    }

    private void section_20000_49999() {
        final int maximumbonus = 1;

    }

    private void section_8000_19999() {
        final int maximumbonus = 1;

    }

    private void section_3000_7999() {
        final int maximumbonus = 1;

    }

    private void section_1000_2999() {
        final int maximumbonus = 1;

    }


    private BigDecimal section_400_999() {
        return BigDecimal.valueOf(15);

    }


    /**************************************/

    /**
     * 1元—3%
     * 2元—7%
     * 3元—10%
     * 4元—15%
     * 5元—15%
     * 6元—15%
     * 7元—15%
     * 8元—10%
     * 9元—7%
     * 10元—3%
     */
    public BigDecimal section_100_399() {
        int s = getRundom(100, 1);
        if (0 < s && s <= 6) {
            int[] arr = {1, 10};
            return getIndexVal(arr);
        } else if (7 <= s && s <= 21) {
            int[] arr = {2, 9};
            return getIndexVal(arr);
        } else if (21 <= s && s <= 41) {
            int[] arr = {3, 8};
            return getIndexVal(arr);
        } else {
            int[] arr = {4, 5, 6, 7};
            return getIndexVal(arr);
        }
    }


    private BigDecimal section_50_99() {
        Random r = new Random();
        int i = r.nextInt(10) + 1;
        if (0 < i && i <= 8) {
            int[] arr = {3, 5};
            return getIndexVal(arr);
        } else {

            return BigDecimal.valueOf(4);
        }
    }


    private BigDecimal section_35_49() {
        return BigDecimal.valueOf(3);
    }

    private BigDecimal section_23_33() {
        int i = getRundom(100, 1);
        if (i < 20) {
            return BigDecimal.valueOf(2);
        } else if (20 < i && i < 95) {
            return BigDecimal.valueOf(3);
        } else
            return BigDecimal.valueOf(4);
    }

    private BigDecimal section_15_23() {
        int i = getRundom(100, 1);
        if (i > 20) {
            return BigDecimal.valueOf(2);
        } else {
            return BigDecimal.valueOf(3);
        }
    }

    private BigDecimal section_10_15() {
        int i = getRundom(100, 1);
        if (i > 20) {
            return BigDecimal.valueOf(1);
        } else {
            return BigDecimal.valueOf(2);
        }
    }


    /**
     * 根据数组随即送
     *
     * @param arr
     * @return
     */
    private static BigDecimal getIndexVal(int[] arr) {
        final BigDecimal resultMoney;
        int index = (int) (Math.random() * arr.length);
        resultMoney = BigDecimal.valueOf(arr[index]);
        return resultMoney;

    }


    /**
     * 添加用户礼包优惠券
     *
     * @param list
     * @param userId
     */
    @Transactional
    public void addUserCouponPackage(String order_id, List<String> list, String userId) {

        User user = userService.getUserBySid(userId);
        SuperRecordModel srm;
        for (String coupon_id : list) {
            int startTime = 50;
            MCoupon coupon = fCouponService.getCouponById(coupon_id);
            srm = new SuperRecordModel();
            //发放用户抵用券
            srm.put("sid", ObjectId.UUID());
            srm.put("user_id", userId);
            srm.put("coupon_id", coupon_id);
            srm.put("withdrawals", "0");
            srm.put("status_flag", "1");
            if (coupon.getMoney() < 100) startTime = 1;
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
            srm.put("start_time", simpleDateFormat.format(DateUtil.day(startTime)));
            srm.put("end_time", simpleDateFormat.format(DateUtil.day(startTime + 50)));
            srm.put("coupon_type", ConponConstant.GIFTS);
            srm.put("order_id", order_id);
            srm.put("c_time", new Date());
            fCouponService.insertUserCoupon(srm);
            fCouponService.updateNumBySid(coupon.getSid());
            FUserLottery fUserLottery = new FUserLottery();
            fUserLottery.setSid(ObjectId.UUID());
            fUserLottery.setOrderId(order_id);
            fUserLottery.setLotteryUserId(userId);
            fUserLottery.setLotteryName(user.getNickname());
            fUserLottery.setLotteryTime(new Date());
            fUserLottery.setLotteryAmount(new BigDecimal(coupon.getMoney()));
            fUserLottery.setStatusFlag("1");
            fUserLottery.setStatusTime(new Date());
            this.add(fUserLottery);
        }
    }


    /**
     * 不中奖不送抵用券 写入中奖纪录 防止多次点击
     *
     * @param userId
     */
    @Transactional
    public void noLettery(String order_id, String userId) {
        User user = userService.getUserBySid(userId);
        FUserLottery fUserLottery = new FUserLottery();
        fUserLottery.setSid(ObjectId.UUID());
        fUserLottery.setOrderId(order_id);
        fUserLottery.setLotteryUserId(userId);
        fUserLottery.setLotteryName(user.getNickname());
        fUserLottery.setLotteryTime(new Date());
        fUserLottery.setLotteryAmount(BigDecimal.ZERO);
        fUserLottery.setStatusFlag("1");
        fUserLottery.setStatusTime(new Date());
        this.add(fUserLottery);
    }

    /**
     * 添加优惠券
     *
     * @param order_id
     * @param list
     * @param store_id
     */

    @Transactional
    public void addClientCouponPackage(String order_id, List<String> list, String store_id) {

        SuperRecordModel superRecordModel = new SuperRecordModel();
        superRecordModel.put("user_id", store_id);

        SuperRecordModel store = storeService.findStoreByUserId(superRecordModel);
        SuperRecordModel srm;
        for (String coupon_id : list) {
            srm = new SuperRecordModel();
            srm.put("sid", ObjectId.UUID());
            srm.put("user_id", store.get("user_id"));
            srm.put("coupon_id", coupon_id);
            srm.put("withdrawals", "0");
            srm.put("status_flag", "1");
            srm.put("start_time", new Date());
            srm.put("end_time", DateUtil.day(50));
            srm.put("coupon_type", ConponConstant.GIFTS);
            srm.put("c_time", new Date());
            fCouponService.insertUserCoupon(srm);
            MCoupon coupon = fCouponService.getCouponById(coupon_id);
            fCouponService.updateNumBySid(coupon.getSid());
            FUserLottery fUserLottery = new FUserLottery();
            fUserLottery.setSid(ObjectId.UUID());
            fUserLottery.setOrderId(order_id);
            fUserLottery.setLotteryUserId((String) store.get("user_id"));
            fUserLottery.setLotteryName((String) store.get("realname"));
            fUserLottery.setLotteryTime(new Date());
            fUserLottery.setLotteryAmount(new BigDecimal(coupon.getMoney()));
            fUserLottery.setStatusFlag("1");
            fUserLottery.setStatusTime(new Date());
            this.add(fUserLottery);
        }
    }


    @Override
    public BigDecimal cdoDraw(Double money) {
        {

            if (money < 10) {
                return BigDecimal.valueOf(0);
            }
            Integer moneys = Integer.valueOf((int) Math.floor(money));
            BigDecimal userBouns = null;
            if (10 <= moneys && moneys < 15) {
                userBouns = csection_10_15();

            } else if (15 <= moneys && moneys < 23) {
                userBouns = csection_15_23();

            } else if (23 <= moneys && moneys < 37) {
                userBouns = csection_23_36();

            } else if (37 <= moneys && moneys < 47) {
                userBouns = csection_37_47();

            } else if (47 <= moneys && moneys < 57) {
                userBouns = csection_47_57();
            } else if (57 <= moneys && moneys < 77) {
                userBouns = csection_57_77();
            } else if (77 <= moneys && moneys < 97) {
                userBouns = csection_77_97();
            } else if (97 <= moneys && moneys < 104) {
                userBouns = csection_97_104();
            } else if (104 <= moneys && moneys < 97) {
                userBouns = csection_47_57();
            } else if (77 <= moneys && moneys < 97) {
                userBouns = csection_47_57();
            } else if (77 <= moneys && moneys < 97) {
                userBouns = csection_47_57();
            }

            return userBouns;
        }
    }

    private BigDecimal csection_97_104() {
        int rundom = getRundom(100, 1);
        if (rundom <= 5) {
            return BigDecimal.valueOf(2);
        } else if (5 < rundom && rundom <= 15) {
            return BigDecimal.valueOf(3);
        } else if (15 < rundom && rundom <= 55) {
            return BigDecimal.valueOf(4);
        } else if (55 < rundom && rundom <= 85) {
            return BigDecimal.valueOf(5);
        } else if (85 < rundom && rundom < 95) {
            return BigDecimal.valueOf(6);
        } else return BigDecimal.valueOf(7);

    }

    private BigDecimal csection_77_97() {
        int rundom = getRundom(100, 1);
        if (rundom <= 5) {
            return BigDecimal.valueOf(3);
        } else if (5 < rundom && rundom <= 15) {
            return BigDecimal.valueOf(4);
        } else if (15 < rundom && rundom <= 55) {
            return BigDecimal.valueOf(5);
        } else if (55 < rundom && rundom <= 85) {
            return BigDecimal.valueOf(6);
        } else if (85 < rundom && rundom < 95) {
            return BigDecimal.valueOf(7);
        } else return BigDecimal.valueOf(8);

    }

    private BigDecimal csection_57_77() {
        int rundom = getRundom(100, 1);
        if (rundom <= 5) {
            return BigDecimal.valueOf(2);
        } else if (5 < rundom && rundom <= 15) {
            return BigDecimal.valueOf(3);
        } else if (15 < rundom && rundom <= 55) {
            return BigDecimal.valueOf(4);
        } else if (55 < rundom && rundom <= 85) {
            return BigDecimal.valueOf(5);
        } else if (85 < rundom && rundom < 95) {
            return BigDecimal.valueOf(6);
        } else return BigDecimal.valueOf(7);
    }

    private BigDecimal csection_47_57() {
        int rundom = getRundom(100, 1);
        if (rundom <= 80) {
            return BigDecimal.valueOf(2);
        } else {
            int[] arr = {3, 4};
            return getIndexVal(arr);
        }
    }

    private BigDecimal csection_37_47() {
        int rundom = getRundom(100, 1);
        if (rundom <= 20) {
            return BigDecimal.valueOf(2);
        } else if (20 < rundom && rundom <= 80) {
            return BigDecimal.valueOf(3);
        } else return BigDecimal.valueOf(4);
    }

    private BigDecimal csection_23_36() {
        int rundom = getRundom(100, 1);
        if (rundom <= 20) {
            return BigDecimal.valueOf(2);
        } else if (20 < rundom && rundom <= 95) {
            return BigDecimal.valueOf(3);
        } else return BigDecimal.valueOf(4);
    }

    private BigDecimal csection_15_23() {
        int rundom = getRundom(100, 1);
        if (rundom <= 80) {
            return BigDecimal.valueOf(2);
        } else
            return BigDecimal.valueOf(3);

    }

    private BigDecimal csection_10_15() {
        int rundom = getRundom(100, 1);
        if (rundom <= 80) {
            return BigDecimal.ONE;
        } else
            return BigDecimal.valueOf(2);
    }

    private BigDecimal csection_100_399() {
        int rundom = getRundom(100, 1);
        if (rundom <= 40) {
            int[] arr = {11, 12, 13, 14, 15};
            return getIndexVal(arr);
        } else if (40 < rundom && rundom <= 70) {
            int[] arr = {8, 9, 10};
            return getIndexVal(arr);
        } else {
            return BigDecimal.valueOf(7);
        }
    }

    private BigDecimal csection_50_99() {
        int[] arr = {3, 4, 5, 6, 7};
        return getIndexVal(arr);
    }

    private BigDecimal csection_35_49() {
        int rundom = getRundom(100, 1);
        if (rundom <= 80) {
            int[] arr = {3, 5};
            return getIndexVal(arr);
        }
        return BigDecimal.valueOf(4);
    }

    private BigDecimal csection_20_34() {
        int rundom = getRundom(100, 1);
        if (rundom >= 26) {
            return BigDecimal.valueOf(2);
        }
        return BigDecimal.valueOf(6);
    }

    private BigDecimal csection_14_19() {
        int[] arr = {1, 3};
        return getIndexVal(arr);
    }

    /**
     * 获取随机数
     *
     * @param max 最大值
     * @param min 最小值
     * @return
     */
    private static int getRundom(int max, int min) {
        Random random = new Random();
        return random.nextInt(max) % (max - min + 1) + min;
    }
}
 